package com.hy.demo.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;

import com.google.android.material.tabs.TabLayout;
import com.hy.frame.util.LogUtil;

public class MixtureScrollView extends androidx.core.widget.NestedScrollView {
    private final static String TAG = "MixtureScrollView";
    private int maxScrollY;

    public MixtureScrollView(@NonNull Context context) {
        super(context);
    }

    public MixtureScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MixtureScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

//    @Override
//    public boolean startNestedScroll(int axes) {
//        LogUtil.d(TAG, String.format("%s: ", "startNestedScroll"));
//        return super.startNestedScroll(axes);
//    }
//
//    @Override
//    public boolean startNestedScroll(int axes, int type) {
//        LogUtil.d(TAG, String.format("%s: ", "startNestedScroll"));
//        return super.startNestedScroll(axes, type);
//    }
//
//    @Override
//    public void stopNestedScroll(int type) {
//        super.stopNestedScroll(type);
//        LogUtil.d(TAG, String.format("%s: ", "stopNestedScroll"));
//    }
//
//    @Override
//    public boolean hasNestedScrollingParent(int type) {
//        LogUtil.d(TAG, String.format("%s: ", "hasNestedScrollingParent"));
//        return super.hasNestedScrollingParent(type);
//    }
//
//    @Override
//    public void setNestedScrollingEnabled(boolean enabled) {
//        super.setNestedScrollingEnabled(enabled);
//        LogUtil.d(TAG, String.format("%s: ", "setNestedScrollingEnabled"));
//    }
//
//    @Override
//    public boolean isNestedScrollingEnabled() {
//        LogUtil.d(TAG, String.format("%s: ", "isNestedScrollingEnabled"));
//        return super.isNestedScrollingEnabled();
//    }
//
//
//    @Override
//    public void stopNestedScroll() {
//        super.stopNestedScroll();
//        LogUtil.d(TAG, String.format("%s: ", "stopNestedScroll"));
//    }
//
//    @Override
//    public boolean hasNestedScrollingParent() {
//        LogUtil.d(TAG, String.format("%s: ", "hasNestedScrollingParent"));
//        return super.hasNestedScrollingParent();
//    }
//
//    @Override
//    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
//        LogUtil.d(TAG, String.format("%s: ", "dispatchNestedFling"));
//        return super.dispatchNestedFling(velocityX, velocityY, consumed);
//    }
//
//    @Override
//    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
//        LogUtil.d(TAG, String.format("%s: ", "dispatchNestedPreFling"));
//        return super.dispatchNestedPreFling(velocityX, velocityY);
//    }
//
//    @Override
//    public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, @NonNull int[] consumed) {
//        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed);
//        LogUtil.d(TAG, String.format("%s: ", "onNestedScroll"));
//    }
//
//    @Override
//    public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
//        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
//        LogUtil.d(TAG, String.format("%s: ", "onNestedScroll"));
//    }
//
//    @Override
//    public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
//        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
//        LogUtil.d(TAG, String.format("%s: ", "onNestedScroll"));
//    }
//
//    @Override
//    public void onStopNestedScroll(@NonNull View target, int type) {
//        super.onStopNestedScroll(target, type);
//        LogUtil.d(TAG, String.format("%s: ", "onStopNestedScroll"));
//    }
//
//
//    @Override
//    public boolean onStartNestedScroll(@NonNull View child, @NonNull View target, int nestedScrollAxes) {
//        LogUtil.d(TAG, String.format("%s: ", "onStartNestedScroll"));
//        return super.onStartNestedScroll(child, target, nestedScrollAxes);
//    }
//
//    @Override
//    public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int nestedScrollAxes) {
//        super.onNestedScrollAccepted(child, target, nestedScrollAxes);
//        LogUtil.d(TAG, String.format("%s: ", "onNestedScrollAccepted"));
//    }
//
//    @Override
//    public void onStopNestedScroll(@NonNull View target) {
//        super.onStopNestedScroll(target);
//        LogUtil.d(TAG, String.format("%s: ", "onStopNestedScroll"));
//    }
//
//    @Override
//    public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed) {
//        super.onNestedPreScroll(target, dx, dy, consumed);
//        LogUtil.d(TAG, String.format("%s: ", "onNestedPreScroll"));
//    }
//
//    @Override
//    public boolean onNestedFling(@NonNull View target, float velocityX, float velocityY, boolean consumed) {
//        LogUtil.d(TAG, String.format("%s: ", "onNestedFling"));
//        return super.onNestedFling(target, velocityX, velocityY, consumed);
//    }
//
//    @Override
//    public boolean onNestedPreFling(@NonNull View target, float velocityX, float velocityY) {
//        LogUtil.d(TAG, String.format("%s: ", "onNestedPreFling"));
//        return super.onNestedPreFling(target, velocityX, velocityY);
//    }
//
//    @Override
//    public int getNestedScrollAxes() {
//        LogUtil.d(TAG, String.format("%s: ", "getNestedScrollAxes"));
//        return super.getNestedScrollAxes();
//    }
//
//    @Override
//    public boolean isSmoothScrollingEnabled() {
//        LogUtil.d(TAG, String.format("%s: ", "isSmoothScrollingEnabled"));
//        return super.isSmoothScrollingEnabled();
//    }
//
//    @Override
//    public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) {
//        super.setSmoothScrollingEnabled(smoothScrollingEnabled);
//        LogUtil.d(TAG, String.format("%s: ", "setSmoothScrollingEnabled"));
//    }
//
//    @Override
//    public boolean pageScroll(int direction) {
//        LogUtil.d(TAG, String.format("%s: ", "pageScroll"));
//        return super.pageScroll(direction);
//    }
//
//    @Override
//    public boolean fullScroll(int direction) {
//        LogUtil.d(TAG, String.format("%s: ", "fullScroll"));
//        return super.fullScroll(direction);
//    }
//
//    @Override
//    public boolean arrowScroll(int direction) {
//        LogUtil.d(TAG, String.format("%s: ", "arrowScroll"));
//        return super.arrowScroll(direction);
//    }
//
//    @Override
//    public void computeScroll() {
//        super.computeScroll();
//        LogUtil.d(TAG, String.format("%s: ", "computeScroll"));
//    }
//
//    @Override
//    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
//        LogUtil.d(TAG, String.format("%s: ", "computeScrollDeltaToGetChildRectOnScreen"));
//        return super.computeScrollDeltaToGetChildRectOnScreen(rect);
//    }
//
//
//    @Override
//    public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes, int type) {
//        super.onNestedScrollAccepted(child, target, axes, type);
//        LogUtil.d(TAG, String.format("%s: axes=%s,type=%s", "onNestedScrollAccepted", axes, type));
//    }
//
//    @Override
//    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
//        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
//        LogUtil.d(TAG, String.format("%s: %sx%s,clamped=%sx%s", "onOverScrolled", scrollX, scrollY, clampedX, clampedY));
//
//    }
//
//    @Override
//    public void dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow, int type, @NonNull int[] consumed) {
//        LogUtil.d(TAG, String.format("%s: ", "dispatchNestedScroll"));
//        super.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed);
//    }
//
//    @Override
//    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow, int type) {
//        LogUtil.d(TAG, String.format("%s: ", "dispatchNestedScroll"));
//        return super.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type);
//    }
//
//    @Override
//    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
//        LogUtil.d(TAG, String.format("%s: ", "dispatchNestedScroll"));
//        return super.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
//    }
//
//    @Override
//    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow, int type) {
//        LogUtil.d(TAG, String.format("%s: %sx%s,consumed=%sx%s", "dispatchNestedPreScroll", dx, dy, consumed[0], consumed[1]));
//        return super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type);
////        return true;
//    }

    /**
     * 设置最大滑动距离
     *
     * @param maxScrollY 最大滑动距离
     */
    public void setMaxScrollY(int maxScrollY) {
        this.maxScrollY = maxScrollY;
    }

    @Override
    public boolean onStartNestedScroll(@NonNull View child, @NonNull View target, int axes, int type) {
        LogUtil.d(TAG, String.format("%s: axes=%s,type=%s", "onStartNestedScroll", axes, type));
        if (maxScrollY == 0) {
            return super.onStartNestedScroll(child, target, axes, type);
        }
        return super.onStartNestedScroll(child, target, axes, type);
    }

    /**
     * @param target   触发嵌套滑动的View
     * @param dx       表示 View 本次 x 方向的滚动的总距离
     * @param dy       表示 View 本次 y 方向的滚动的总距离
     * @param consumed 表示父布局消费的水平和垂直距离
     * @param type     触发滑动事件的类型
     */
    @Override
    public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
        int scrollY = getScrollY();
        LogUtil.d(TAG, String.format("%s %s: %sx%s,consumed=%sx%s,scrollY=%s", "onNestedPreScroll", target, dx, dy, consumed[0], consumed[1], scrollY));
        if (vTab == null) {
            checkTab();
            return;
        }
        if (maxScrollY == 0) {
            super.onNestedPreScroll(target, dx, dy, consumed, type);
            return;
        }
//        super.onNestedPreScroll(target, dx, dy, consumed, type);
//        if (true) {
//            return;
//        }
        //dy 大于0 向上滚动
        //tab还未显示
        boolean hiddenTop = dy > 0 && getScrollY() < maxScrollY;
        //向下滚动 并且 当前子View已不能向下滚动时
        boolean showTop = dy < 0 && getScrollY() > 0 && !target.canScrollVertically(-1);
        if (hiddenTop || showTop) {
            scrollBy(0, dy);
            consumed[1] = dy;
        } else {
            super.onNestedPreScroll(target, dx, dy, consumed, type);
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        LogUtil.d(TAG, String.format("%s: %sx%s,old=%sx%s", "onScrollChanged", l, t, oldl, oldt));
        if (vTab != null && maxScrollY > 0) {
            if (t < maxScrollY) {
                //不贴边
                if (vTab.getParent() != tabGroup) {
                    scrollGroup.removeView(vTab);
                    tabGroup.removeView(vTmp);
                    tabGroup.addView(vTab, 0);
                }
            } else {
                //贴边
                if (vTab.getParent() != scrollGroup) {
                    tabGroup.removeView(vTab);
                    scrollGroup.removeView(vTmp);
                    tabGroup.addView(vTmp, 0);
                    scrollGroup.addView(vTab);
                }
            }
        }
    }

    private TabLayout vTab;
    private ViewPager2 vPager;
    private ViewGroup tabGroup;
    private ViewGroup scrollGroup;
    private View vTmp;
    private int tabTop;
    private int tabHeight;


    public void checkTab() {
        if (getChildCount() == 0) {
            return;
        }
        this.vTab = findTabLayout(getChildAt(0), TabLayout.class);
        this.vPager = findTabLayout(getChildAt(0), ViewPager2.class);
        if (this.vTab != null) {
            this.tabHeight = vTab.getMeasuredHeight();
            tabTop = calViewTop(vTab, MixtureScrollView.class);
            setMaxScrollY(tabTop);
            vPager.getLayoutParams().height = getMeasuredHeight() - tabHeight;
            tabGroup = (ViewGroup) vTab.getParent();
            scrollGroup = (ViewGroup) getParent();
            vTmp = new View(getContext());
            vTmp.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, tabHeight));
            LogUtil.d(TAG, "checkTab: top=" + tabTop);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> T findTabLayout(View view, Class<T> cls) {
        if (view.getClass() == cls) {
            return (T) view;
        }
        if (view instanceof ViewGroup) {
            ViewGroup group = (ViewGroup) view;
            for (int i = 0; i < group.getChildCount(); i++) {
                T child = findTabLayout(group.getChildAt(i), cls);
                if (child != null) {
                    return child;
                }
            }
        }
        return null;
    }

    private int calViewTop(View view, Class<?> root) {
        if (view.getClass() == root) {
            return 0;
        }
        int top = view.getTop();
        if (view.getParent() != null) {
            top += calViewTop((View) view.getParent(), root);
        }
        return top;
    }
}
